library(tidyverse)
library(sf)
library(tmap)

1 Rudiments

setwd("~/Dropbox/Teaching/SpatialAnalysis-MontevideoWorkshop2019/Notebooks/Montevideo_Data/Accidentes2006-2010")
Accidents <- st_read("accidentes2006-2010.shp")
Accidents = st_set_crs(Accidents, 32721)

setwd("~/Dropbox/Teaching/SpatialAnalysis-MontevideoWorkshop2019/Notebooks/Montevideo_Data/afe_estaciones")
Stations <- st_read("afe_estaciones.shp")
Stations <- st_set_crs(Stations, 32721)

setwd("~/Dropbox/Teaching/SpatialAnalysis-MontevideoWorkshop2019/Notebooks/Montevideo_Data/Vectoriales_2011")
Uruguay <- st_read("ine_depto.shp")
Uruguay <- st_set_crs(Uruguay, 32721)

setwd("~/Dropbox/Teaching/SpatialAnalysis-MontevideoWorkshop2019/Notebooks/Montevideo_Data/CyclingMontevideoData/v_bi_bicicircuitos")
Bicicircuitos <- st_read("v_bi_bicicircuitos.shp")
tm_shape(Uruguay) + 
  tm_polygons()

tm_shape(Montevideo) + 
  tm_polygons() +
  tm_shape(Accidents) + tm_bubbles()

st_bbox(Uruguay)
     xmin      ymin      xmax      ymax 
 366582.2 6127918.5  858252.1 6671738.4 
st_bbox(Montevideo)
     xmin      ymin      xmax      ymax 
 551982.7 6133498.9  589227.2 6159810.3 
tm_shape(Uruguay, bbox = st_bbox(Montevideo)) + 
  tm_polygons(col = "deepskyblue1") 

Nort Carolina SIDS data

nc = st_read(system.file("shape/nc.shp", package="sf"))
Reading layer `nc' from data source `/Library/Frameworks/R.framework/Versions/3.5/Resources/library/sf/shape/nc.shp' using driver `ESRI Shapefile'
Simple feature collection with 100 features and 14 fields
geometry type:  MULTIPOLYGON
dimension:      XY
bbox:           xmin: -84.32385 ymin: 33.88199 xmax: -75.45698 ymax: 36.58965
epsg (SRID):    4267
proj4string:    +proj=longlat +datum=NAD27 +no_defs

2 The road to a map

tm_shape(nc) + tm_polygons(col="BIR79")
tm_shape(nc) + tm_polygons(col="BIR79") + 
  tm_compass() + tm_scale_bar()

2.1 Legends - tm_layout function

tm_shape(nc) + tm_polygons(col="BIR79") + 
    tm_layout(legend.position = c(0.2,0.03),
              scale=0.8,
              #legend.title.size = 1,
              legend.frame = T)

tm_shape(nc) + tm_polygons(col="BIR79", title = "Births 1979 - 84") + 
    tm_layout(legend.position = c(0.01,0.65),
              scale=0.65,
              legend.frame = T)

tm_shape(nc) + tm_polygons(col="BIR79", title = "Births 1979 - 84") + 
    tm_layout(title = "THI IS MY TITLE",
              legend.position = c(0.01,0.05),
              scale = 0.9,
              legend.frame = T) + 
   tm_add_legend(type = c("fill"),
                labels = c("Some Area","Other Area"), 
                col = c("#66c2a5","#e5c494"),
                title = "Other Areas") +
  tm_add_legend(type = "symbol", 
                labels = c("A point","Other Point"), 
                col = c("#e78ac3","grey"))

2.2 Where is the south?

But coming back to our map, it needs a compass so your audience know where noth and east are.

tm_shape(nc) + tm_polygons(col="BIR79", title = "Births 1979 - 84") + 
    tm_layout(legend.position = c(0.01,0.65),
              scale=0.65,
              legend.frame = T) + 
    tm_compass() 

NA
tm_shape(nc) + tm_polygons(col="BIR79", title = "Births 1979 - 84") + 
    tm_layout(legend.position = c(0.01,0.65),
              scale=0.65,
              legend.frame = T) + 
    tm_compass(size = 5, type = "8star") 

NA
tm_shape(nc) + tm_polygons(col="BIR79", title = "Births 1979 - 84") + 
    tm_layout(legend.position = c(0.01,0.65),
              scale=0.65,
              legend.frame = T) + 
    tm_compass(size = 5, type = "rose", lwd = 3, show.labels = 0) 

2.3 The scale

tm_shape(nc) + tm_polygons(col="BIR79", title = "Births 1979 - 84") + 
    tm_layout(legend.position = c(0.01,0.65),
              scale=0.65,
              legend.frame = T) + 
    tm_compass(size = 5, type = "rose", lwd = 3) + 
    tm_scale_bar()

tm_shape(nc) + tm_polygons(col="BIR79", title = "Births 1979 - 84") + 
    tm_layout(legend.position = c(0.01,0.65),
              scale=0.65,
              legend.frame = T) + 
    tm_compass(size = 5, type = "rose", lwd = 3) + 
    tm_scale_bar(breaks = c(0,50,100,150,200),size = 2, position = c(0.06,0))

In the documentation In the documentation In the documentation

tm_shape(nc) + tm_polygons(col="BIR79", title = "Births 1979 - 84") + 
    tm_layout(legend.position = c(0.01,0.65),
              scale=0.65,
              legend.frame = T) + 
    tm_compass(size = 5, type = "rose", lwd = 3) + 
    tm_scale_bar(breaks = c(0,50,100,150,200),size = 1, position = c(0.06,0),
                 lwd = 5, color.dark = "darkgreen", color.light = "blue")

MyMap <- tm_shape(nc) + tm_polygons(col="BIR79", title = "Births 1979 - 84") + 
    tm_layout(legend.position = c(0.01,0.65),
              scale=0.65,
              legend.frame = T,
              bg.color = "lightblue") + 
    tm_compass(size = 5, type = "rose", lwd = 3) + 
    tm_scale_bar(breaks = c(0,50,100,150,200),size = 1, position = c(0.06,0),
                 lwd = 3)
MyMap

2.4 Mode: View

tmap_mode("view")
tmap mode set to interactive viewing
MyMap
Compass not supported in view mode.
legend.postion is used for plot mode. Use view.legend.position in tm_view to set the legend position in view mode.
tmap_mode("plot")
tmap mode set to plotting
UruguayMap <- tm_shape(Uruguay) + 
  tm_polygons()
tmap_leaflet(UruguayMap)

2.5 Colors

tm_shape(nc) + tm_polygons(col="BIR79", title = "Births 1979 - 84", palette = "Blues") + 
    tm_layout(legend.position = c(0.01,0.65),
              scale=0.65,
              legend.frame = T,
              bg.color = "lightblue") + 
    tm_compass(size = 5, type = "rose", lwd = 3) + 
    tm_scale_bar(breaks = c(0,50,100,150,200),size = 1, position = c(0.06,0),
                 lwd = 3)

library(RColorBrewer)
display.brewer.all()

library(RColorBrewer)
tm_shape(nc) + tm_polygons(col="BIR79", title = "Births 1979 - 84", palette = "YlGnBu") + 
    tm_layout(legend.position = c(0.01,0.65),
              scale=0.65,
              legend.frame = T,
              bg.color = "lightblue") + 
    tm_compass(size = 5, type = "rose", lwd = 3) + 
    tm_scale_bar(breaks = c(0,50,100,150,200),size = 1, position = c(0.06,0),
                 lwd = 3)

tm_shape(nc) + tm_polygons(col="BIR79", title = "Births 1979 - 84", palette = "-YlGnBu") + 
    tm_layout(legend.position = c(0.01,0.65),
              scale=0.65,
              legend.frame = T,
              bg.color = "lightblue") + 
    tm_compass(size = 5, type = "rose", lwd = 3) + 
    tm_scale_bar(breaks = c(0,50,100,150,200),size = 1, position = c(0.06,0),
                 lwd = 3)

summary(nc$BIR79)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
    319    1336    2636    4224    4889   30757 

Breaks <- c(0, 2000, 4000, 6000, 31000)
Labels <- c("0 - 2000", "2000 - 4000", "4000 - 6000", ">6000")
tm_shape(nc) + tm_polygons(col="BIR79", title = "Births 1979 - 84", palette = "YlGnBu",
                           breaks = Breaks, labels = Labels) + 
    tm_layout(legend.position = c(0.01,0.65),
              scale=0.65,
              legend.frame = T,
              bg.color = "lightblue") + 
    tm_compass(size = 5, type = "rose", lwd = 3) + 
    tm_scale_bar(breaks = c(0,50,100,150,200),size = 1, position = c(0.06,0),
                 lwd = 3)

tm_shape(nc) + tm_polygons(col="BIR79", title = "Births 1979 - 84", palette = MyPalette,
                           breaks = Breaks, labels = Labels) + 
    tm_layout(legend.position = c(0.01,0.65),
              scale=0.65,
              legend.frame = T,
              bg.color = "lightblue") + 
    tm_compass(size = 5, type = "rose", lwd = 3) + 
    tm_scale_bar(breaks = c(0,50,100,150,200),size = 1, position = c(0.06,0),
                 lwd = 3)

3 Auxiliar map

MontevideoMap <- tm_shape(Montevideo) + 
  tm_polygons() +
  tm_shape(Accidents) + tm_bubbles()
UruguayMap <- tm_shape(Uruguay) + 
  tm_polygons()
library(grid)
MontevideoMap
print(UruguayMap, vp = viewport(0.17, 0.8, width = 0.25, height = 0.25))

MontevideoMap <- tm_shape(Montevideo) + 
  tm_polygons(col = "deepskyblue1") 
MontevideoNeigh <- Uruguay %>% filter(NOMBRE %in% c("SAN JOSE", "CANELONES", "MONTEVIDEO"))
AuxMap <- tm_shape(MontevideoNeigh) + tm_polygons(col = "green")
MontevideoMap
print(AuxMap, vp = viewport(0.17, 0.8, width = 0.2, height = 0.2))

Our map needs some context!

MontevideoBox <- st_bbox(Montevideo) %>% st_as_sf()
Error in UseMethod("st_as_sf") : 
  no applicable method for 'st_as_sf' applied to an object of class "bbox"

AuxMap <- tm_shape(MontevideoNeigh) + tm_polygons(col = "green") + 
  tm_shape(MontevideoBox) + tm_polygons(border.col = "red", lwd = 2.5, alpha = 0.3)
  
MontevideoMap
print(AuxMap, vp = viewport(0.17, 0.8, width = 0.2, height = 0.2))

4 Faceted maps

tm_shape(Montevideo) + tm_polygons() +
  tm_shape(Accidents) + tm_dots(alpha = 0.5) + tm_facets(by = "ANIO")

Accidents2006 <- Accidents %>% filter(ANIO == "2006")
Accidents2010 <- Accidents %>% filter(ANIO == "2010")
Complements <- tm_compass() + tm_scale_bar()
Map2006 <- tm_shape(Accidents2006) + tm_dots() + Complements
Map2010 <- tm_shape(Accidents2010) + tm_dots() + Complements
tmap_arrange(Map2006, Map2010)

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKYXV0aG9yOiAiT3JsYW5kbyBTYWJvZ2FsIgpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6IAogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICAgIHRvYzogeWVzCi0tLQoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHNmKQpsaWJyYXJ5KHRtYXApCmBgYAoKCiNSdWRpbWVudHMKCmBgYHtyfQpzZXR3ZCgifi9Ecm9wYm94L1RlYWNoaW5nL1NwYXRpYWxBbmFseXNpcy1Nb250ZXZpZGVvV29ya3Nob3AyMDE5L05vdGVib29rcy9Nb250ZXZpZGVvX0RhdGEvQWNjaWRlbnRlczIwMDYtMjAxMCIpCkFjY2lkZW50cyA8LSBzdF9yZWFkKCJhY2NpZGVudGVzMjAwNi0yMDEwLnNocCIpCkFjY2lkZW50cyA9IHN0X3NldF9jcnMoQWNjaWRlbnRzLCAzMjcyMSkKCnNldHdkKCJ+L0Ryb3Bib3gvVGVhY2hpbmcvU3BhdGlhbEFuYWx5c2lzLU1vbnRldmlkZW9Xb3Jrc2hvcDIwMTkvTm90ZWJvb2tzL01vbnRldmlkZW9fRGF0YS9hZmVfZXN0YWNpb25lcyIpClN0YXRpb25zIDwtIHN0X3JlYWQoImFmZV9lc3RhY2lvbmVzLnNocCIpClN0YXRpb25zIDwtIHN0X3NldF9jcnMoU3RhdGlvbnMsIDMyNzIxKQoKc2V0d2QoIn4vRHJvcGJveC9UZWFjaGluZy9TcGF0aWFsQW5hbHlzaXMtTW9udGV2aWRlb1dvcmtzaG9wMjAxOS9Ob3RlYm9va3MvTW9udGV2aWRlb19EYXRhL1ZlY3RvcmlhbGVzXzIwMTEiKQpVcnVndWF5IDwtIHN0X3JlYWQoImluZV9kZXB0by5zaHAiKQpVcnVndWF5IDwtIHN0X3NldF9jcnMoVXJ1Z3VheSwgMzI3MjEpCgpzZXR3ZCgifi9Ecm9wYm94L1RlYWNoaW5nL1NwYXRpYWxBbmFseXNpcy1Nb250ZXZpZGVvV29ya3Nob3AyMDE5L05vdGVib29rcy9Nb250ZXZpZGVvX0RhdGEvQ3ljbGluZ01vbnRldmlkZW9EYXRhL3ZfYmlfYmljaWNpcmN1aXRvcyIpCkJpY2ljaXJjdWl0b3MgPC0gc3RfcmVhZCgidl9iaV9iaWNpY2lyY3VpdG9zLnNocCIpCgpgYGAKCmBgYHtyfQp0bV9zaGFwZShVcnVndWF5KSArIAogIHRtX3BvbHlnb25zKCkKYGBgCgpgYGB7cn0KTW9udGV2aWRlbyA8LSBVcnVndWF5ICU+JSBmaWx0ZXIoTk9NQlJFPT0iTU9OVEVWSURFTyIpCmBgYAoKCmBgYHtyfQp0bV9zaGFwZShNb250ZXZpZGVvKSArIAogIHRtX3BvbHlnb25zKCkgKwogIHRtX3NoYXBlKEFjY2lkZW50cykgKyB0bV9idWJibGVzKCkKYGBgCgpgYGB7cn0KTXlNYXAgPC0gdG1fc2hhcGUoVXJ1Z3VheSkgKyAKICB0bV9wb2x5Z29ucyhjb2wgPSAiZGVlcHNreWJsdWUxIikgCmBgYAoKYGBge3J9Ck15TWFwCmBgYAoKCmBgYHtyfQpzdF9iYm94KFVydWd1YXkpCnN0X2Jib3goTW9udGV2aWRlbykKYGBgCgoKYGBge3J9CnRtX3NoYXBlKFVydWd1YXksIGJib3ggPSBzdF9iYm94KE1vbnRldmlkZW8pKSArIAogIHRtX3BvbHlnb25zKGNvbCA9ICJkZWVwc2t5Ymx1ZTEiKSAKYGBgCgoKYGBge3J9CgpgYGAKCgpbTm9ydCBDYXJvbGluYSBTSURTIGRhdGFdKGh0dHBzOi8vbm93b3NhZC5naXRodWIuaW8vc3BEYXRhL3JlZmVyZW5jZS9uYy5zaWRzLmh0bWwpCgpgYGB7cn0KbmMgPSBzdF9yZWFkKHN5c3RlbS5maWxlKCJzaGFwZS9uYy5zaHAiLCBwYWNrYWdlPSJzZiIpKQpgYGAKCmBgYHtyfQp0bV9zaGFwZShuYykgKyB0bV9wb2x5Z29ucyhjb2w9IkJJUjc5IikKYGBgCgojVGhlIHJvYWQgdG8gYSBtYXAKCmBgYHtyfQp0bV9zaGFwZShuYykgKyB0bV9wb2x5Z29ucyhjb2w9IkJJUjc5IikKYGBgCgpgYGB7cn0KdG1fc2hhcGUobmMpICsgdG1fcG9seWdvbnMoY29sPSJCSVI3OSIpICsgCiAgdG1fY29tcGFzcygpICsgdG1fc2NhbGVfYmFyKCkKYGBgCgojIyBMZWdlbmRzIC0gdG1fbGF5b3V0IGZ1bmN0aW9uCgpgYGB7cn0KdG1fc2hhcGUobmMpICsgdG1fcG9seWdvbnMoY29sPSJCSVI3OSIpICsgCiAgICB0bV9sYXlvdXQobGVnZW5kLnBvc2l0aW9uID0gYygwLjIsMC4wMyksCiAgICAgICAgICAgICAgc2NhbGU9MC44LAogICAgICAgICAgICAgIGxlZ2VuZC5mcmFtZSA9IFQpCmBgYAoKCmBgYHtyfQp0bV9zaGFwZShuYykgKyB0bV9wb2x5Z29ucyhjb2w9IkJJUjc5IiwgdGl0bGUgPSAiQmlydGhzIDE5NzkgLSA4NCIpICsgCiAgICB0bV9sYXlvdXQobGVnZW5kLnBvc2l0aW9uID0gYygwLjAxLDAuNjUpLAogICAgICAgICAgICAgIHNjYWxlPTAuNjUsCiAgICAgICAgICAgICAgbGVnZW5kLmZyYW1lID0gVCkKYGBgCgpgYGB7cn0KdG1fc2hhcGUobmMpICsgdG1fcG9seWdvbnMoY29sPSJCSVI3OSIsIHRpdGxlID0gIkJpcnRocyAxOTc5IC0gODQiKSArIAogICAgdG1fbGF5b3V0KHRpdGxlID0gIlRISSBJUyBNWSBUSVRMRSIsCiAgICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gYygwLjAxLDAuMDUpLAogICAgICAgICAgICAgIHNjYWxlID0gMC45LAogICAgICAgICAgICAgIGxlZ2VuZC5mcmFtZSA9IFQpICsgCiAgIHRtX2FkZF9sZWdlbmQodHlwZSA9IGMoImZpbGwiKSwKICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIlNvbWUgQXJlYSIsIk90aGVyIEFyZWEiKSwgCiAgICAgICAgICAgICAgICBjb2wgPSBjKCIjNjZjMmE1IiwiI2U1YzQ5NCIpLAogICAgICAgICAgICAgICAgdGl0bGUgPSAiT3RoZXIgQXJlYXMiKSArCiAgdG1fYWRkX2xlZ2VuZCh0eXBlID0gInN5bWJvbCIsIAogICAgICAgICAgICAgICAgbGFiZWxzID0gYygiQSBwb2ludCIsIk90aGVyIFBvaW50IiksIAogICAgICAgICAgICAgICAgY29sID0gYygiI2U3OGFjMyIsImdyZXkiKSkKYGBgCgoKIyNXaGVyZSBpcyB0aGUgc291dGg/CgpCdXQgY29taW5nIGJhY2sgdG8gb3VyIG1hcCwgaXQgbmVlZHMgYSBjb21wYXNzIHNvIHlvdXIgYXVkaWVuY2Uga25vdyB3aGVyZSBub3RoIGFuZCBlYXN0IGFyZS4KCmBgYHtyfQp0bV9zaGFwZShuYykgKyB0bV9wb2x5Z29ucyhjb2w9IkJJUjc5IiwgdGl0bGUgPSAiQmlydGhzIDE5NzkgLSA4NCIpICsgCiAgICB0bV9sYXlvdXQobGVnZW5kLnBvc2l0aW9uID0gYygwLjAxLDAuNjUpLAogICAgICAgICAgICAgIHNjYWxlPTAuNjUsCiAgICAgICAgICAgICAgbGVnZW5kLmZyYW1lID0gVCkgKyAKICAgIHRtX2NvbXBhc3MoKSAKICAKYGBgCgoKYGBge3J9CnRtX3NoYXBlKG5jKSArIHRtX3BvbHlnb25zKGNvbD0iQklSNzkiLCB0aXRsZSA9ICJCaXJ0aHMgMTk3OSAtIDg0IikgKyAKICAgIHRtX2xheW91dChsZWdlbmQucG9zaXRpb24gPSBjKDAuMDEsMC42NSksCiAgICAgICAgICAgICAgc2NhbGU9MC42NSwKICAgICAgICAgICAgICBsZWdlbmQuZnJhbWUgPSBUKSArIAogICAgdG1fY29tcGFzcyhzaXplID0gNSwgdHlwZSA9ICI4c3RhciIpIAogIApgYGAKCmBgYHtyfQp0bV9zaGFwZShuYykgKyB0bV9wb2x5Z29ucyhjb2w9IkJJUjc5IiwgdGl0bGUgPSAiQmlydGhzIDE5NzkgLSA4NCIpICsgCiAgICB0bV9sYXlvdXQobGVnZW5kLnBvc2l0aW9uID0gYygwLjAxLDAuNjUpLAogICAgICAgICAgICAgIHNjYWxlPTAuNjUsCiAgICAgICAgICAgICAgbGVnZW5kLmZyYW1lID0gVCkgKyAKICAgIHRtX2NvbXBhc3Moc2l6ZSA9IDUsIHR5cGUgPSAicm9zZSIsIGx3ZCA9IDMsIHNob3cubGFiZWxzID0gMCkgCmBgYAoKCiMjVGhlIHNjYWxlCgpgYGB7cn0KdG1fc2hhcGUobmMpICsgdG1fcG9seWdvbnMoY29sPSJCSVI3OSIsIHRpdGxlID0gIkJpcnRocyAxOTc5IC0gODQiKSArIAogICAgdG1fbGF5b3V0KGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC4wMSwwLjY1KSwKICAgICAgICAgICAgICBzY2FsZT0wLjY1LAogICAgICAgICAgICAgIGxlZ2VuZC5mcmFtZSA9IFQpICsgCiAgICB0bV9jb21wYXNzKHNpemUgPSA1LCB0eXBlID0gInJvc2UiLCBsd2QgPSAzKSArIAogICAgdG1fc2NhbGVfYmFyKCkKYGBgCgoKCmBgYHtyfQp0bV9zaGFwZShuYykgKyB0bV9wb2x5Z29ucyhjb2w9IkJJUjc5IiwgdGl0bGUgPSAiQmlydGhzIDE5NzkgLSA4NCIpICsgCiAgICB0bV9sYXlvdXQobGVnZW5kLnBvc2l0aW9uID0gYygwLjAxLDAuNjUpLAogICAgICAgICAgICAgIHNjYWxlPTAuNjUsCiAgICAgICAgICAgICAgbGVnZW5kLmZyYW1lID0gVCkgKyAKICAgIHRtX2NvbXBhc3Moc2l6ZSA9IDUsIHR5cGUgPSAicm9zZSIsIGx3ZCA9IDMpICsgCiAgICB0bV9zY2FsZV9iYXIoYnJlYWtzID0gYygwLDUwLDEwMCwxNTAsMjAwKSxzaXplID0gMiwgcG9zaXRpb24gPSBjKDAuMDYsMCkpCmBgYAoKCgpJbiB0aGUgW2RvY3VtZW50YXRpb25dKGh0dHBzOi8vd3d3LnJkb2N1bWVudGF0aW9uLm9yZy9wYWNrYWdlcy90bWFwL3ZlcnNpb25zLzIuMi90b3BpY3MvdG1fbGF5b3V0KQpJbiB0aGUgW2RvY3VtZW50YXRpb25dKGh0dHBzOi8vd3d3LnJkb2N1bWVudGF0aW9uLm9yZy9wYWNrYWdlcy90bWFwL3ZlcnNpb25zLzIuMi90b3BpY3MvdG1fY29tcGFzcykKSW4gdGhlIFtkb2N1bWVudGF0aW9uXShodHRwczovL3d3dy5yZG9jdW1lbnRhdGlvbi5vcmcvcGFja2FnZXMvdG1hcC92ZXJzaW9ucy8yLjIvdG9waWNzL3RtX3NjYWxlX2JhcikKCmBgYHtyfQp0bV9zaGFwZShuYykgKyB0bV9wb2x5Z29ucyhjb2w9IkJJUjc5IiwgdGl0bGUgPSAiQmlydGhzIDE5NzkgLSA4NCIpICsgCiAgICB0bV9sYXlvdXQobGVnZW5kLnBvc2l0aW9uID0gYygwLjAxLDAuNjUpLAogICAgICAgICAgICAgIHNjYWxlPTAuNjUsCiAgICAgICAgICAgICAgbGVnZW5kLmZyYW1lID0gVCkgKyAKICAgIHRtX2NvbXBhc3Moc2l6ZSA9IDUsIHR5cGUgPSAicm9zZSIsIGx3ZCA9IDMpICsgCiAgICB0bV9zY2FsZV9iYXIoYnJlYWtzID0gYygwLDUwLDEwMCwxNTAsMjAwKSxzaXplID0gMSwgcG9zaXRpb24gPSBjKDAuMDYsMCksCiAgICAgICAgICAgICAgICAgbHdkID0gNSwgY29sb3IuZGFyayA9ICJkYXJrZ3JlZW4iLCBjb2xvci5saWdodCA9ICJibHVlIikKYGBgCgoKYGBge3J9CgpgYGAKCgpgYGB7cn0KTXlNYXAgPC0gdG1fc2hhcGUobmMpICsgdG1fcG9seWdvbnMoY29sPSJCSVI3OSIsIHRpdGxlID0gIkJpcnRocyAxOTc5IC0gODQiKSArIAogICAgdG1fbGF5b3V0KGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC4wMSwwLjY1KSwKICAgICAgICAgICAgICBzY2FsZT0wLjY1LAogICAgICAgICAgICAgIGxlZ2VuZC5mcmFtZSA9IFQsCiAgICAgICAgICAgICAgYmcuY29sb3IgPSAibGlnaHRibHVlIikgKyAKICAgIHRtX2NvbXBhc3Moc2l6ZSA9IDUsIHR5cGUgPSAicm9zZSIsIGx3ZCA9IDMpICsgCiAgICB0bV9zY2FsZV9iYXIoYnJlYWtzID0gYygwLDUwLDEwMCwxNTAsMjAwKSxzaXplID0gMSwgcG9zaXRpb24gPSBjKDAuMDYsMCksCiAgICAgICAgICAgICAgICAgbHdkID0gMykKCmBgYAoKYGBge3J9Ck15TWFwCmBgYAoKIyNNb2RlOiBWaWV3CgpgYGB7cn0KdG1hcF9tb2RlKCJ2aWV3IikKTXlNYXAKYGBgCgoKYGBge3J9CnRtYXBfbW9kZSgicGxvdCIpCmBgYAoKCmBgYHtyfQpVcnVndWF5TWFwIDwtIHRtX3NoYXBlKFVydWd1YXkpICsgCiAgdG1fcG9seWdvbnMoKQoKdG1hcF9sZWFmbGV0KFVydWd1YXlNYXApCmBgYAoKIyNDb2xvcnMKCmBgYHtyfQp0bV9zaGFwZShuYykgKyB0bV9wb2x5Z29ucyhjb2w9IkJJUjc5IiwgdGl0bGUgPSAiQmlydGhzIDE5NzkgLSA4NCIsIHBhbGV0dGUgPSAiQmx1ZXMiKSArIAogICAgdG1fbGF5b3V0KGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC4wMSwwLjY1KSwKICAgICAgICAgICAgICBzY2FsZT0wLjY1LAogICAgICAgICAgICAgIGxlZ2VuZC5mcmFtZSA9IFQsCiAgICAgICAgICAgICAgYmcuY29sb3IgPSAibGlnaHRibHVlIikgKyAKICAgIHRtX2NvbXBhc3Moc2l6ZSA9IDUsIHR5cGUgPSAicm9zZSIsIGx3ZCA9IDMpICsgCiAgICB0bV9zY2FsZV9iYXIoYnJlYWtzID0gYygwLDUwLDEwMCwxNTAsMjAwKSxzaXplID0gMSwgcG9zaXRpb24gPSBjKDAuMDYsMCksCiAgICAgICAgICAgICAgICAgbHdkID0gMykKCmBgYAoKYGBge3J9CmxpYnJhcnkoUkNvbG9yQnJld2VyKQpkaXNwbGF5LmJyZXdlci5hbGwoKQpgYGAKCgpgYGB7cn0KdG1fc2hhcGUobmMpICsgdG1fcG9seWdvbnMoY29sPSJCSVI3OSIsIHRpdGxlID0gIkJpcnRocyAxOTc5IC0gODQiLCBwYWxldHRlID0gIllsR25CdSIpICsgCiAgICB0bV9sYXlvdXQobGVnZW5kLnBvc2l0aW9uID0gYygwLjAxLDAuNjUpLAogICAgICAgICAgICAgIHNjYWxlPTAuNjUsCiAgICAgICAgICAgICAgbGVnZW5kLmZyYW1lID0gVCwKICAgICAgICAgICAgICBiZy5jb2xvciA9ICJsaWdodGJsdWUiKSArIAogICAgdG1fY29tcGFzcyhzaXplID0gNSwgdHlwZSA9ICJyb3NlIiwgbHdkID0gMykgKyAKICAgIHRtX3NjYWxlX2JhcihicmVha3MgPSBjKDAsNTAsMTAwLDE1MCwyMDApLHNpemUgPSAxLCBwb3NpdGlvbiA9IGMoMC4wNiwwKSwKICAgICAgICAgICAgICAgICBsd2QgPSAzKQpgYGAKCmBgYHtyfQp0bV9zaGFwZShuYykgKyB0bV9wb2x5Z29ucyhjb2w9IkJJUjc5IiwgdGl0bGUgPSAiQmlydGhzIDE5NzkgLSA4NCIsIHBhbGV0dGUgPSAiLVlsR25CdSIpICsgCiAgICB0bV9sYXlvdXQobGVnZW5kLnBvc2l0aW9uID0gYygwLjAxLDAuNjUpLAogICAgICAgICAgICAgIHNjYWxlPTAuNjUsCiAgICAgICAgICAgICAgbGVnZW5kLmZyYW1lID0gVCwKICAgICAgICAgICAgICBiZy5jb2xvciA9ICJsaWdodGJsdWUiKSArIAogICAgdG1fY29tcGFzcyhzaXplID0gNSwgdHlwZSA9ICJyb3NlIiwgbHdkID0gMykgKyAKICAgIHRtX3NjYWxlX2JhcihicmVha3MgPSBjKDAsNTAsMTAwLDE1MCwyMDApLHNpemUgPSAxLCBwb3NpdGlvbiA9IGMoMC4wNiwwKSwKICAgICAgICAgICAgICAgICBsd2QgPSAzKQpgYGAKCgpgYGB7cn0Kc3VtbWFyeShuYyRCSVI3OSkKYGBgCgoKYGBge3J9Cm5jICU+JSBnZ3Bsb3QoYWVzKHg9QklSNzkpKSArIGdlb21faGlzdG9ncmFtKCkKYGBgCgoKCmBgYHtyfQpCcmVha3MgPC0gYygwLCAyMDAwLCA0MDAwLCA2MDAwLCAzMTAwMCkKTGFiZWxzIDwtIGMoIjAgLSAyMDAwIiwgIjIwMDAgLSA0MDAwIiwgIjQwMDAgLSA2MDAwIiwgIj42MDAwIikKYGBgCgoKYGBge3J9CnRtX3NoYXBlKG5jKSArIHRtX3BvbHlnb25zKGNvbD0iQklSNzkiLCB0aXRsZSA9ICJCaXJ0aHMgMTk3OSAtIDg0IiwgcGFsZXR0ZSA9ICJZbEduQnUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBCcmVha3MsIGxhYmVscyA9IExhYmVscykgKyAKICAgIHRtX2xheW91dChsZWdlbmQucG9zaXRpb24gPSBjKDAuMDEsMC42NSksCiAgICAgICAgICAgICAgc2NhbGU9MC42NSwKICAgICAgICAgICAgICBsZWdlbmQuZnJhbWUgPSBULAogICAgICAgICAgICAgIGJnLmNvbG9yID0gImxpZ2h0Ymx1ZSIpICsgCiAgICB0bV9jb21wYXNzKHNpemUgPSA1LCB0eXBlID0gInJvc2UiLCBsd2QgPSAzKSArIAogICAgdG1fc2NhbGVfYmFyKGJyZWFrcyA9IGMoMCw1MCwxMDAsMTUwLDIwMCksc2l6ZSA9IDEsIHBvc2l0aW9uID0gYygwLjA2LDApLAogICAgICAgICAgICAgICAgIGx3ZCA9IDMpCmBgYAoKYGBge3J9Ck15UGFsZXR0ZSA8LSBjKCIjZjJmMGY3IiwgIiNjYmM5ZTIiLCAiIzllOWFjOCIsICIjNmE1MWEzIikKYGBgCgoKYGBge3J9CnRtX3NoYXBlKG5jKSArIHRtX3BvbHlnb25zKGNvbD0iQklSNzkiLCB0aXRsZSA9ICJCaXJ0aHMgMTk3OSAtIDg0IiwgcGFsZXR0ZSA9IE15UGFsZXR0ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gQnJlYWtzLCBsYWJlbHMgPSBMYWJlbHMpICsgCiAgICB0bV9sYXlvdXQobGVnZW5kLnBvc2l0aW9uID0gYygwLjAxLDAuNjUpLAogICAgICAgICAgICAgIHNjYWxlPTAuNjUsCiAgICAgICAgICAgICAgbGVnZW5kLmZyYW1lID0gVCwKICAgICAgICAgICAgICBiZy5jb2xvciA9ICJsaWdodGJsdWUiKSArIAogICAgdG1fY29tcGFzcyhzaXplID0gNSwgdHlwZSA9ICJyb3NlIiwgbHdkID0gMykgKyAKICAgIHRtX3NjYWxlX2JhcihicmVha3MgPSBjKDAsNTAsMTAwLDE1MCwyMDApLHNpemUgPSAxLCBwb3NpdGlvbiA9IGMoMC4wNiwwKSwKICAgICAgICAgICAgICAgICBsd2QgPSAzKQpgYGAKCgojQXV4aWxpYXIgbWFwCgpgYGB7cn0KTW9udGV2aWRlb01hcCA8LSB0bV9zaGFwZShNb250ZXZpZGVvKSArIAogIHRtX3BvbHlnb25zKCkgKwogIHRtX3NoYXBlKEFjY2lkZW50cykgKyB0bV9idWJibGVzKCkKClVydWd1YXlNYXAgPC0gdG1fc2hhcGUoVXJ1Z3VheSkgKyAKICB0bV9wb2x5Z29ucygpCmBgYAoKYGBge3J9CmxpYnJhcnkoZ3JpZCkKYGBgCgoKYGBge3J9Ck1vbnRldmlkZW9NYXAKcHJpbnQoVXJ1Z3VheU1hcCwgdnAgPSB2aWV3cG9ydCgwLjE3LCAwLjgsIHdpZHRoID0gMC4yNSwgaGVpZ2h0ID0gMC4yNSkpCmBgYAoKYGBge3J9Ck1vbnRldmlkZW9NYXAgPC0gdG1fc2hhcGUoTW9udGV2aWRlbykgKyAKICB0bV9wb2x5Z29ucyhjb2wgPSAiZGVlcHNreWJsdWUxIikgCgoKTW9udGV2aWRlb05laWdoIDwtIFVydWd1YXkgJT4lIGZpbHRlcihOT01CUkUgJWluJSBjKCJTQU4gSk9TRSIsICJDQU5FTE9ORVMiLCAiTU9OVEVWSURFTyIpKQoKQXV4TWFwIDwtIHRtX3NoYXBlKE1vbnRldmlkZW9OZWlnaCkgKyB0bV9wb2x5Z29ucyhjb2wgPSAiZ3JlZW4iKQpgYGAKCmBgYHtyfQpNb250ZXZpZGVvTWFwCnByaW50KEF1eE1hcCwgdnAgPSB2aWV3cG9ydCgwLjE3LCAwLjgsIHdpZHRoID0gMC4yLCBoZWlnaHQgPSAwLjIpKQpgYGAKCgpPdXIgbWFwIG5lZWRzIHNvbWUgY29udGV4dCEKCmBgYHtyfQpNb250ZXZpZGVvQm94IDwtIHN0X2Jib3goTW9udGV2aWRlbykgJT4lIHN0X2FzX3NmYygpICNXaHkgbm90IHN0X2FzX3NmPwpgYGAKCmBgYHtyfQp0bV9zaGFwZShNb250ZXZpZGVvQm94KSArIHRtX3BvbHlnb25zKGNvbCA9ICJ3aGl0ZSIsIGJvcmRlci5jb2wgPSAiYmx1ZSIsIGx3ZCA9IDQpCiNwbG90KHN0X2dlb21ldHJ5KE1vbnRldmlkZW9Cb3gpKQpgYGAKCgpgYGB7cn0KCkF1eE1hcCA8LSB0bV9zaGFwZShNb250ZXZpZGVvTmVpZ2gpICsgdG1fcG9seWdvbnMoY29sID0gImdyZWVuIikgKyAKICB0bV9zaGFwZShNb250ZXZpZGVvQm94KSArIHRtX3BvbHlnb25zKGJvcmRlci5jb2wgPSAicmVkIiwgbHdkID0gMi41LCBhbHBoYSA9IDAuMykKICAKCk1vbnRldmlkZW9NYXAKcHJpbnQoQXV4TWFwLCB2cCA9IHZpZXdwb3J0KDAuMTcsIDAuOCwgd2lkdGggPSAwLjIsIGhlaWdodCA9IDAuMikpCmBgYAoKCiNGYWNldGVkIG1hcHMKCmBgYHtyfQp0bV9zaGFwZShNb250ZXZpZGVvKSArIHRtX3BvbHlnb25zKCkgKwogIHRtX3NoYXBlKEFjY2lkZW50cykgKyB0bV9kb3RzKGFscGhhID0gMC41KSArIHRtX2ZhY2V0cyhieSA9ICJBTklPIikKYGBgCgpgYGB7cn0KdG1fc2hhcGUoTW9udGV2aWRlbykgKyB0bV9wb2x5Z29ucygpICsKICB0bV9zaGFwZShBY2NpZGVudHMpICsgdG1fZG90cyhhbHBoYSA9IDAuNSkgKyB0bV9mYWNldHMoYnkgPSAiQU5JTyIsIG5yb3cgPSAxKQpgYGAKCmBgYHtyfQp0bV9zaGFwZShNb250ZXZpZGVvKSArIHRtX3BvbHlnb25zKCkgKwogIHRtX3NoYXBlKEFjY2lkZW50cykgKyB0bV9kb3RzKGFscGhhID0gMC41KSArIHRtX2ZhY2V0cyhieSA9ICJBTklPIiwgbmNvbCA9IDEpCmBgYAoKYGBge3J9CkFjY2lkZW50czIwMDYgPC0gQWNjaWRlbnRzICU+JSBmaWx0ZXIoQU5JTyA9PSAiMjAwNiIpCkFjY2lkZW50czIwMTAgPC0gQWNjaWRlbnRzICU+JSBmaWx0ZXIoQU5JTyA9PSAiMjAxMCIpCgpDb21wbGVtZW50cyA8LSB0bV9jb21wYXNzKCkgKyB0bV9zY2FsZV9iYXIoKQoKTWFwMjAwNiA8LSB0bV9zaGFwZShBY2NpZGVudHMyMDA2KSArIHRtX2RvdHMoKSArIENvbXBsZW1lbnRzCk1hcDIwMTAgPC0gdG1fc2hhcGUoQWNjaWRlbnRzMjAxMCkgKyB0bV9kb3RzKCkgKyBDb21wbGVtZW50cwpgYGAKCmBgYHtyfQp0bWFwX2FycmFuZ2UoTWFwMjAwNiwgTWFwMjAxMCkKYGBgCgpgYGB7cn0KCmBgYAo=